<html>
<head><meta charset="utf-8"><title>Default arguments and type inference · general · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/index.html">general</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Default.20arguments.20and.20type.20inference.html">Default arguments and type inference</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="230256704"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Default%20arguments%20and%20type%20inference/near/230256704" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Default.20arguments.20and.20type.20inference.html#230256704">(Mar 14 2021 at 17:41)</a>:</h4>
<p>Why does this give a type inference error?</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">struct</span> <span class="nc">Foo</span><span class="o">&lt;</span><span class="n">A</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">()</span><span class="o">&gt;</span><span class="p">(</span><span class="n">A</span><span class="p">);</span><span class="w"></span>

<span class="k">impl</span><span class="o">&lt;</span><span class="n">A</span>: <span class="nb">Default</span><span class="o">&gt;</span><span class="w"> </span><span class="n">Foo</span><span class="o">&lt;</span><span class="n">A</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">new</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nc">Self</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="bp">Self</span><span class="p">(</span><span class="n">A</span>::<span class="n">default</span><span class="p">())</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">Foo</span>::<span class="n">new</span><span class="p">();</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<div class="codehilite"><pre><span></span><code>error[E0283]: type annotations needed
 --&gt; src/main.rs:9:5
  |
5 |     fn new() -&gt; Self { Self(A::default()) }
  |     ---------------- required by `Foo::&lt;A&gt;::new`
...
9 |     Foo::new();
  |     ^^^^^^^^ cannot infer type for type parameter `A`
  |
  = note: cannot satisfy `_: Default`
</code></pre></div>



<a name="230256764"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Default%20arguments%20and%20type%20inference/near/230256764" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Default.20arguments.20and.20type.20inference.html#230256764">(Mar 14 2021 at 17:42)</a>:</h4>
<p>I would have expected it to guess the default argument <code>()</code>, which does implement <code>Default</code></p>



<a name="230262218"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Default%20arguments%20and%20type%20inference/near/230262218" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Henry-Mantilla <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Default.20arguments.20and.20type.20inference.html#230262218">(Mar 14 2021 at 19:24)</a>:</h4>
<p>Default generic type parameters only work for types, not for paths / functions; I guess because having both inference and a SFINAE-like default fallback is a tricky thing for a language to design properly (_e.g._ if code later on makes type inference possible, then we have spooky action at a distance changing the semantics of the original call).</p>
<ul>
<li>I personally think that such a feature should disable implicit type inference for that parameter (like it happens for types: <code>let foo: Foo;</code> and <code>let foo: Foo&lt;_&gt;</code> do not mean the same thing) and it would thus be something tied to functions rather than types; the drawback would be that <code>let foo: Foo&lt;B&gt; = new_foo()</code> would, for instance, fail (it should be <code>let foo: Foo&lt;B&gt; = new_foo::&lt;_&gt;()</code>).</li>
</ul>



<a name="230266632"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Default%20arguments%20and%20type%20inference/near/230266632" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Blake Oren <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Default.20arguments.20and.20type.20inference.html#230266632">(Mar 14 2021 at 20:43)</a>:</h4>
<p><code>struct Foo&lt;A = ()&gt;(A);</code> is generic over any Zero Sized Types, which do implement the Default trait. Since <code>Foo::new()</code> is generic you have to specify the type on construction. As shown below, <code>let foo: Foo</code> is valid and results in the Zero Sized Type unit where <code>let baz: Foo&lt;_&gt;</code> fails to compile as the type can't be coerced. Other ZSTs that also implement the Default trait can be given as type annotations show with <code>x</code>, <code>y</code>, and <code>z</code>.</p>
<p><a href="https://doc.rust-lang.org/std/primitive.unit.html">Doc: Primitive Unit</a><br>
<a href="https://doc.rust-lang.org/nomicon/exotic-sizes.html">Nomicon: Exotic Sizes</a></p>
<p><a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=c541e3d2e1c052cf7f361dca2357dcae">Playground Link</a></p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="cp">#![allow(dead_code)]</span><span class="w"></span>
<span class="cp">#![allow(unused_variables)]</span><span class="w"></span>

<span class="cp">#[derive(Debug, Default)]</span><span class="w"></span>
<span class="k">struct</span> <span class="nc">Nothing</span><span class="p">;</span><span class="w"></span>

<span class="cp">#[derive(Debug)]</span><span class="w"></span>
<span class="k">struct</span> <span class="nc">Foo</span><span class="o">&lt;</span><span class="n">A</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">()</span><span class="o">&gt;</span><span class="p">(</span><span class="n">A</span><span class="p">);</span><span class="w"></span>

<span class="k">impl</span><span class="o">&lt;</span><span class="n">A</span>: <span class="nb">Default</span><span class="o">&gt;</span><span class="w"> </span><span class="n">Foo</span><span class="o">&lt;</span><span class="n">A</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">new</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nc">Self</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="bp">Self</span><span class="p">(</span><span class="n">A</span>::<span class="n">default</span><span class="p">())</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Foo</span>::<span class="o">&lt;</span><span class="p">()</span><span class="o">&gt;</span>::<span class="n">new</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Foo</span>::<span class="o">&lt;</span><span class="n">Nothing</span><span class="o">&gt;</span>::<span class="n">new</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Foo</span>::<span class="o">&lt;</span><span class="kt">usize</span><span class="o">&gt;</span>::<span class="n">new</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="fm">dbg!</span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">,</span><span class="w"> </span><span class="n">z</span><span class="p">);</span><span class="w"></span>

<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">foo</span>: <span class="nc">Foo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Foo</span>::<span class="n">new</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="c1">// let baz: Foo&lt;_&gt; = Foo::new();</span>
<span class="w">    </span><span class="c1">//     ---  ^^^^^^ cannot infer type</span>
<span class="w">    </span><span class="c1">//     |</span>
<span class="w">    </span><span class="c1">//     consider giving `baz` the explicit type `Foo&lt;_&gt;`, with the type parameters specified</span>
<span class="w">    </span><span class="fm">dbg!</span><span class="p">(</span><span class="n">foo</span><span class="p">);</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<div class="codehilite" data-code-language="Text only"><pre><span></span><code>[src/main.rs:20] x = Foo(
    (),
)
[src/main.rs:20] y = Foo(
    Nothing,
)
[src/main.rs:20] z = Foo(
    0,
)
[src/main.rs:27] foo = Foo(
    (),
)
</code></pre></div>



<a name="230270467"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Default%20arguments%20and%20type%20inference/near/230270467" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Default.20arguments.20and.20type.20inference.html#230270467">(Mar 14 2021 at 21:49)</a>:</h4>
<p>Yes I'm aware that other types can be used instead of <code>()</code>; that's the whole point of having a generic parameter. What I'm trying to understand is how it's possible to retrofit a default extra parameter, like <code>Box&lt;T, A = ()&gt;</code>, when you have a constructor that doesn't take a value of type <code>A</code> but builds it in some other way (e.g. via <code>Default</code>). Isn't this what type defaults are for?</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>